package com.whq.thrift.api.thrift.as.service.service;

import java.lang.reflect.Method;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.whq.common.CollectionUtil;
import com.whq.common.StringUtil;
import com.whq.common.loadclass.DynamicLoadClassPathUtil;
import com.whq.thrift.api.common.constants.CommonErrorCodeConstants;
import com.whq.thrift.api.common.redis.RedisHelper;
import com.whq.thrift.api.common.spring.ReloadableConfManager;
import com.whq.thrift.api.common.thriftserver.AbstractApiJsonService;
import com.whq.thrift.api.common.thriftserver.ResponseBase;
import com.whq.thrift.api.thrift.as.service.constants.AsMixedErrorCodeConstants;

import net.rubyeye.xmemcached.MemcachedClient;

public class AsBaseSpringService extends AbstractApiJsonService {
	private static final Logger LOGGER = LoggerFactory.getLogger(AsBaseSpringService.class);
	
	private ReloadableConfManager reloadableConfManager = null;
	
	private SqlSessionFactory sqlSessionFactory;
	
	private SqlSession sqlSession;
	
	private MemcachedClient memcachedClient01;
	
	private MemcachedClient memcachedClient02;
	
	private MemcachedClient memcachedClient03;
	
	private MemcachedClient memcachedClient04;
	
	private MemcachedClient memcachedClient05;
	
	private RedisHelper redisHelper01;
	
	private RedisHelper redisHelper02;
	
	private RedisHelper redisHelper03;
	
	private RedisHelper redisHelper04;
	
	private RedisHelper redisHelper05;
	
	private static boolean inited = false;
	
	private static final Map<String, Object> MAP_METHOD_INSTANCE = new HashMap<String, Object>(0);
	@SuppressWarnings("rawtypes")
	private static final Map<String, Class> MAP_METHOD_CLASS = new HashMap<String, Class>(0);
	
	@Override
	protected ResponseBase doHandleApiJsonRequest(String method, Map<String, String> params, Map<String, String> ctx, String flowId) {
		if (StringUtil.isBlank(method)) {
			return new ResponseBase(CommonErrorCodeConstants.ERR_CODE_LACK_PARAM, "缺少参数：method");
		}
		
		loadMethodClass();
		
		String subClassPath = "";
		String classMethod = "";
		List<String> identityMethodList = StringUtil.split2list(method, "\\.");
		if ( (identityMethodList != null) && (!identityMethodList.isEmpty()) ) {
			int cnt = identityMethodList.size();
			
			classMethod = identityMethodList.get(cnt - 1);
			identityMethodList.remove(cnt - 1);
			subClassPath = CollectionUtil.convertList2String(identityMethodList, ".");
		}
		
		Class<?> clz = MAP_METHOD_CLASS.get(method);
		Object adi = MAP_METHOD_INSTANCE.get(method);
		if ( (clz == null) || (adi == null) ) {
			String methodClassRootPath = reloadableConfManager.getPropertyValue("method.classpath.prefix", null, "com.whq.thrift.api.thrift.as.service.method");
			String classname = methodClassRootPath + "." + subClassPath;
			try {
				clz = getClass().getClassLoader().loadClass(classname);
				if (clz != null) {
					MAP_METHOD_CLASS.put(method, clz);
					// 从Class中实例出一个对象
					adi = clz.newInstance(); 
					if (adi != null) {
						MAP_METHOD_INSTANCE.put(method, adi);
					}
				}
			} catch (Exception e) {
				LOGGER.error("load class [" + classname + "] exception: ", e);
			}
		}
		
		if ( (clz != null) && (adi != null) ) {
			try {
				Method m = clz.getMethod(classMethod, AsBaseSpringService.class, String.class, Map.class, Map.class);
				return (ResponseBase) m.invoke(adi, this, method, params, ctx);
			} catch (Exception e) {
				LOGGER.error("excute [" + method + "] exception: ", e);
			}
		}
		
		// 其他业务
		return new ResponseBase(AsMixedErrorCodeConstants.ERR_CODE_EXEC_THRIFT_API_ERROR, "执行api接口[" + method + "]出错");
	}
	
	private void loadMethodClass() {
		if (inited) {
			return ;
		}
		inited = true;
		
		String methodClassRootPath = reloadableConfManager.getPropertyValue("method.class.rootpath", null, "");
		
		DynamicLoadClassPathUtil.loadClassPath(methodClassRootPath);
	}

	public ReloadableConfManager getReloadableConfManager() {
		return reloadableConfManager;
	}

	public void setReloadableConfManager(ReloadableConfManager reloadableConfManager) {
		this.reloadableConfManager = reloadableConfManager;
	}

	public SqlSessionFactory getSqlSessionFactory() {
		return sqlSessionFactory;
	}

	public void setSqlSessionFactory(SqlSessionFactory sqlSessionFactory) {
		this.sqlSessionFactory = sqlSessionFactory;
	}

	public SqlSession getSqlSession() {
		return sqlSession;
	}

	public void setSqlSession(SqlSession sqlSession) {
		this.sqlSession = sqlSession;
	}

	public MemcachedClient getMemcachedClient01() {
		return memcachedClient01;
	}

	public void setMemcachedClient01(MemcachedClient memcachedClient01) {
		this.memcachedClient01 = memcachedClient01;
	}

	public MemcachedClient getMemcachedClient02() {
		return memcachedClient02;
	}

	public void setMemcachedClient02(MemcachedClient memcachedClient02) {
		this.memcachedClient02 = memcachedClient02;
	}

	public MemcachedClient getMemcachedClient03() {
		return memcachedClient03;
	}

	public void setMemcachedClient03(MemcachedClient memcachedClient03) {
		this.memcachedClient03 = memcachedClient03;
	}

	public MemcachedClient getMemcachedClient04() {
		return memcachedClient04;
	}

	public void setMemcachedClient04(MemcachedClient memcachedClient04) {
		this.memcachedClient04 = memcachedClient04;
	}

	public MemcachedClient getMemcachedClient05() {
		return memcachedClient05;
	}

	public void setMemcachedClient05(MemcachedClient memcachedClient05) {
		this.memcachedClient05 = memcachedClient05;
	}

	public RedisHelper getRedisHelper01() {
		return redisHelper01;
	}

	public void setRedisHelper01(RedisHelper redisHelper01) {
		this.redisHelper01 = redisHelper01;
	}

	public RedisHelper getRedisHelper02() {
		return redisHelper02;
	}

	public void setRedisHelper02(RedisHelper redisHelper02) {
		this.redisHelper02 = redisHelper02;
	}

	public RedisHelper getRedisHelper03() {
		return redisHelper03;
	}

	public void setRedisHelper03(RedisHelper redisHelper03) {
		this.redisHelper03 = redisHelper03;
	}

	public RedisHelper getRedisHelper04() {
		return redisHelper04;
	}

	public void setRedisHelper04(RedisHelper redisHelper04) {
		this.redisHelper04 = redisHelper04;
	}

	public RedisHelper getRedisHelper05() {
		return redisHelper05;
	}

	public void setRedisHelper05(RedisHelper redisHelper05) {
		this.redisHelper05 = redisHelper05;
	}
	
}
